<!-- The exported code uses Tailwind CSS. Install Tailwind CSS in your dev environment to ensure all styles work. -->
<template>
  <div class="flex-1 flex flex-col h-screen">
    <!-- 顶部操作栏 -->
    <div class="bg-white p-4 border-b flex justify-between items-center">
      <div class="flex items-center">
        <h1 class="text-xl font-bold">AI 对话</h1>
      </div>
      <button
        @click="createNewChat"
        class="bg-blue-600 hover:bg-blue-700 text-white px-6 py-3 rounded-lg flex items-center cursor-pointer whitespace-nowrap transition-all duration-200 shadow-md hover:shadow-lg font-medium"
      >
        <el-icon class="mr-2 text-lg">
          <Plus />
        </el-icon>
        新建对话
      </button>
    </div>
    <!-- 主体内容区 -->
    <div class="flex-1 flex overflow-hidden">
      <!-- 左侧历史对话列表 -->
      <div ref="chatHistoryRef" class="bg-white border-r overflow-hidden flex flex-col" style="width: 280px; min-width: 200px; max-width: 350px; resize: horizontal;">
        <div class="p-4 bg-gradient-to-r from-blue-50 to-indigo-50 border-b border-blue-100">
          <div class="flex items-center justify-between mb-4">
            <h3 class="font-semibold text-gray-800 text-base">历史对话</h3>
            <button 
              @click="createNewChat"
              class="bg-blue-600 hover:bg-blue-700 text-white px-3 py-1.5 rounded-md flex items-center text-xs font-medium transition-all duration-200 shadow-sm hover:shadow-md"
            >
              <el-icon class="mr-1 text-sm"><Plus /></el-icon>新建
            </button>
          </div>
          <div class="relative bg-white rounded-lg border border-gray-200 shadow-sm focus-within:ring-2 focus-within:ring-blue-500 focus-within:border-transparent transition-all duration-200">
            <div class="flex items-center">
              <el-icon class="ml-3 text-gray-400 flex-shrink-0"><Search /></el-icon>
              <input
                v-model="searchKeyword"
                type="text"
                placeholder="搜索对话历史"
                class="flex-1 px-3 py-2.5 bg-transparent border-0 text-sm focus:outline-none"
              />
            </div>
          </div>
        </div>
        
        <div class="flex-1 overflow-y-auto">
          <div 
            v-for="(chat, index) in chatHistory" 
            :key="chat.id"
            @click="selectChat(index)"
            :class="[
              'p-3 border-b cursor-pointer hover:bg-gray-50 transition-colors',
              currentChatIndex === index ? 'bg-blue-50' : ''
            ]"
          >
            <div class="flex justify-between">
              <div class="flex-1 min-w-0 pr-3">
                <h3 class="font-medium text-gray-800 truncate mb-1.5">{{ chat.title }}</h3>
                <div class="flex items-center text-xs text-gray-500">
                  <span class="whitespace-nowrap">{{ formatDate(chat.updateTime) }}</span>
                  <span class="mx-1.5 text-gray-300">•</span>
                  <span class="truncate">Token: {{ chat.totalToken }}</span>
                </div>
              </div>
              <div class="relative group">
                <button class="p-1 rounded-full text-gray-400 hover:bg-gray-100 hover:text-gray-600">
                  <el-icon><MoreFilled /></el-icon>
                </button>
                <div class="absolute right-0 mt-1 hidden group-hover:block bg-white shadow-lg rounded-md border z-10 w-24">
                  <div class="py-1">
                    <a @click.stop="renameChat(index)" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 cursor-pointer">
                      重命名
                    </a>
                    <div class="border-t border-gray-100"></div>
                    <a @click.stop="deleteChat(index)" class="block px-4 py-2 text-sm text-red-500 hover:bg-gray-100 cursor-pointer">
                      删除
                    </a>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
        
        <!-- 分页组件 -->
        <div class="p-3 border-t mt-auto">
          <div class="flex items-center justify-between mb-2">
            <span class="text-xs text-gray-500">共 {{ totalCount }} 条</span>
            <select 
              v-model="pageParams.limit" 
              @change="handleSizeChange($event.target.value)"
              class="ml-2 border rounded py-1 px-2 text-xs bg-gray-50"
            >
              <option v-for="size in [6, 16, 32, 64]" :key="size" :value="size">{{ size }}/页</option>
            </select>
          </div>
          <div class="flex justify-center">
            <div class="inline-flex rounded-md shadow-sm">
              <button 
                @click="handlePrevPage" 
                :disabled="pageParams.page === 1"
                class="px-2 py-1 text-xs rounded-l-md border bg-white disabled:opacity-50"
              >
                上一页
              </button>
              <button 
                v-for="page in displayedPages" 
                :key="page"
                @click="handleCurrentChange(page)"
                :class="[
                  'px-2 py-1 text-xs border-t border-b bg-white',
                  pageParams.page === page ? 'bg-blue-50 text-blue-600 font-medium' : '',
                  'border-l-0'
                ]"
              >
                {{ page }}
              </button>
              <button 
                @click="handleNextPage" 
                :disabled="pageParams.page >= totalPages"
                class="px-2 py-1 text-xs rounded-r-md border bg-white disabled:opacity-50 border-l-0"
              >
                下一页
              </button>
            </div>
          </div>
        </div>
      </div>
      <!-- 右侧对话区域 -->
      <div class="flex-1 flex flex-col bg-gray-50">
        <!-- 对话内容区 -->
        <div class="flex-1 overflow-y-auto p-4" ref="chatContentRef">
          <div
            v-if="currentChat.messages.length === 0"
            class="h-full flex flex-col items-center justify-center text-gray-400"
          >
            <!-- <img
              src="https://readdy.ai/api/search-image?query=A%20minimalist%20illustration%20of%20a%20friendly%20AI%20assistant%20or%20chatbot%20icon%20with%20a%20simple%20smiling%20face%2C%20clean%20lines%2C%20soft%20colors%2C%20on%20a%20plain%20light%20background%2C%20modern%20tech%20aesthetic%2C%20professional%20looking&width=200&height=200&seq=1&orientation=squarish"
              alt="AI助手" class="w-32 h-32 mb-4 rounded-full shadow-md" />
            <p class="text-lg">开始一个新的对话吧！</p>
            <p class="text-sm mt-2">您可以询问任何问题，AI 助手将为您提供帮助。</p> -->
            <Welcome
              icon="https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*s5sNRo5LjfQAAAAAAAAAAAAADgCCAQ/fmt.webp"
              title="Hello, I'm Eon Mind AI"
              description="有任何问题都可以问我，我会尽力回答您的问题。"
            />
          </div>
          <template v-else>
            <div v-for="(message, msgIndex) in currentChat.messages" :key="msgIndex" class="mb-6">
              <div :class="['flex items-start gap-1', message.role === 'user' ? 'justify-end' : 'justify-start']">
                <!-- AI 头像 -->
                <div v-if="message.role !== 'user'" class="flex-shrink-0">
                  <div class="w-8 h-8 rounded-full bg-blue-100 flex items-center justify-center">
                    <el-icon>
                      <ChatDotRound />
                    </el-icon>
                  </div>
                </div>
                
                <!-- 消息内容 -->
                <div :class="['max-w-3xl', message.role === 'user' ? 'order-1' : '']">
                  <Bubble
                    :loading="
                      isTyping &&
                      msgIndex === currentChat.messages.length - 1 &&
                      message.role === 'assistant' &&
                      !message.content
                    "
                    :content="message.content"
                    :messageRender="renderMarkdown"
                    :typing="
                      msgIndex === currentChat.messages.length - 1 &&
                      message.role === 'assistant' &&
                      isNewMessage
                        ? { step: 6, interval: 30, suffix: '💗' }
                        : false
                    "
                  >
                    <template #footer="{ content }">
                      <!-- 优化后的附件显示区域 -->
                      <div
                        v-if="message.messageMediaList && message.messageMediaList.length > 0"
                        class="mt-2 p-3 bg-gray-50 rounded-lg border border-gray-200"
                      >
                        <div class="flex items-center mb-2 text-sm font-medium text-gray-700">
                          <FileOutlined class="mr-1" />
                          <span>附件 ({{ message.messageMediaList.length }})</span>
                        </div>
                        <Flex vertical gap="small">
                          <div
                            v-for="(media, index) in message.messageMediaList"
                            :key="index"
                            class="relative group"
                          >
                            <!-- 图片附件 -->
                            <div
                              v-if="isImageFile(media.data)"
                              class="relative border border-gray-300 rounded-lg overflow-hidden bg-white shadow-sm hover:shadow-md transition-shadow"
                            >
                              <img
                                :src="media.data"
                                :alt="media.name"
                                class="w-full max-w-xs h-auto object-cover cursor-pointer"
                                @click="previewImage(media.data)"
                              />
                              <div class="absolute top-2 left-2 bg-black bg-opacity-70 text-white text-xs px-2 py-1 rounded">
                                <PictureOutlined class="mr-1" />
                                图片
                              </div>
                              <div class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black to-transparent p-2">
                                <div class="text-white text-xs truncate">{{ media.name || '图片文件' }}</div>
                              </div>
                            </div>
                            
                            <!-- 视频附件 -->
                            <div
                              v-else-if="isVideoFile(media.data)"
                              class="relative border border-gray-300 rounded-lg overflow-hidden bg-white shadow-sm hover:shadow-md transition-shadow"
                            >
                              <video
                                :src="media.data"
                                class="w-full max-w-xs h-auto cursor-pointer"
                                controls
                                preload="metadata"
                              />
                              <div class="absolute top-2 left-2 bg-black bg-opacity-70 text-white text-xs px-2 py-1 rounded">
                                <VideoCameraOutlined class="mr-1" />
                                视频
                              </div>
                            </div>
                            
                            <!-- 音频附件 -->
                            <div
                              v-else-if="isAudioFile(media.data)"
                              class="flex items-center p-3 border border-gray-300 rounded-lg bg-white shadow-sm hover:shadow-md transition-shadow"
                            >
                              <div class="flex-shrink-0 w-10 h-10 bg-green-100 rounded-lg flex items-center justify-center mr-3">
                                <SoundOutlined class="text-green-600 text-lg" />
                              </div>
                              <div class="flex-1 min-w-0">
                                <audio :src="media.data" controls class="w-full max-w-xs"></audio>
                                <div class="text-sm font-medium text-gray-900 truncate mt-1">
                                  {{ media.name || '音频文件' }}
                                </div>
                                <div class="text-xs text-gray-500">
                                  {{ getFileTypeText(media.data) }}
                                </div>
                              </div>
                            </div>
                            
                            <!-- 其他类型附件 -->
                            <div
                              v-else
                              class="flex items-center p-3 border border-gray-300 rounded-lg bg-white shadow-sm hover:shadow-md transition-shadow cursor-pointer"
                              @click="downloadFile(media)"
                            >
                              <div class="flex-shrink-0 w-10 h-10 bg-blue-100 rounded-lg flex items-center justify-center mr-3">
                                <FileTextOutlined class="text-blue-600 text-lg" />
                              </div>
                              <div class="flex-1 min-w-0">
                                <div class="text-sm font-medium text-gray-900 truncate">
                                  {{ media.name || '附件文件' }}
                                </div>
                                <div class="text-xs text-gray-500">
                                  {{ getFileTypeText(media.data) }}
                                </div>
                              </div>
                              <div class="flex-shrink-0 ml-2">
                                <DownloadOutlined class="text-gray-400 hover:text-blue-600" />
                              </div>
                            </div>
                          </div>
                        </Flex>
                      </div>
                      
                      <Space :size="token.paddingXXS">
                        <Button
                          type="text"
                          size="small"
                          :icon="h(CopyOutlined)"
                          @click="copyMessage(message.content)"
                        />
                        <div class="text-xs text-gray-400 ml-2">{{ message.time }}</div>
                      </Space>
                    </template>
                  </Bubble>
                </div>
                
                <!-- 用户头像 -->
                <div v-if="message.role === 'user'" class="flex-shrink-0 order-2">
                  <div class="w-8 h-8 rounded-full bg-blue-600 flex items-center justify-center text-white">
                    <el-icon>
                      <User />
                    </el-icon>
                  </div>
                </div>
              </div>
            </div>
          </template>
        </div>
        <!-- 输入区域 -->
        <div class="bg-white border-t p-4">
          <!-- 模型和助手选择区域 -->
          <div class="mb-3 flex justify-between items-center">
            <div class="flex items-center space-x-4">
              <!-- 模型选择 -->
              <div class="relative">
                <div @click="openModelSelector" class="flex items-center px-3 py-2 bg-gradient-to-r from-blue-50 to-indigo-50 border-2 border-blue-200 rounded-lg cursor-pointer hover:from-blue-100 hover:to-indigo-100 hover:border-blue-300 transition-all duration-200 shadow-sm hover:shadow-md">
                  <div class="flex items-center">
                    <el-icon class="text-blue-600 text-base mr-2">
                      <ChatDotRound />
                    </el-icon>
                    <div class="flex flex-col">
                      <span class="text-xs text-gray-500 font-medium">当前模型</span>
                      <span class="font-bold text-gray-800 text-sm">{{ currentModel }}</span>
                    </div>
                    <span
                      v-if="currentModelTypeName"
                      class="ml-2 text-xs px-2 py-1 rounded-full bg-blue-100 text-blue-700 font-medium border border-blue-200"
                    >{{ currentModelTypeName }}</span>
                  </div>
                  <el-icon class="ml-2 text-blue-600">
                    <ArrowDown />
                  </el-icon>
                </div>
              </div>

              <!-- 助手选择 -->
              <div class="flex items-center">
                <div v-if="currentAssistant" class="flex items-center px-3 py-2 bg-gradient-to-r from-green-50 to-emerald-50 border-2 border-green-200 rounded-lg mr-3 transition-all duration-200 shadow-sm hover:shadow-md cursor-pointer" @click="showAssistantSelector = true">
                  <el-icon class="text-green-600 text-base mr-2">
                    <UserFilled />
                  </el-icon>
                  <div class="flex flex-col">
                    <span class="text-xs text-green-600 font-medium">当前助手</span>
                    <span class="font-bold text-green-800 text-sm">{{ currentAssistant.assistantName }}</span>
                  </div>
                  <el-icon class="ml-2 text-green-600">
                    <ArrowDown />
                  </el-icon>
                </div>
                <el-button v-if="!currentAssistant" type="success" plain size="default" @click="showAssistantSelector = true">
                  <el-icon class="mr-1"><UserFilled /></el-icon>
                  选择助手
                </el-button>
                <el-button
                  v-if="currentAssistant"
                  type="danger"
                  plain
                  size="small"
                  @click="clearAssistant"
                  class="ml-2"
                >
                  <el-icon class="mr-1"><Close /></el-icon>清除
                </el-button>
              </div>
              
              <!-- 知识库选择 -->
              <div class="flex items-center ml-4">
                <div v-if="currentKnowledgeBase" class="flex items-center px-3 py-2 bg-gradient-to-r from-purple-50 to-pink-50 border-2 border-purple-200 rounded-lg mr-3 transition-all duration-200 shadow-sm hover:shadow-md cursor-pointer" @click="openKnowledgeBaseSelector">
                  <el-icon class="text-purple-600 text-base mr-2">
                    <Folder />
                  </el-icon>
                  <div class="flex flex-col">
                    <span class="text-xs text-purple-600 font-medium">当前知识库</span>
                    <span class="font-bold text-purple-800 text-sm">{{ currentKnowledgeBase.name }}</span>
                  </div>
                  <el-icon class="ml-2 text-purple-600">
                    <ArrowDown />
                  </el-icon>
                </div>
                <el-button v-if="!currentKnowledgeBase" type="primary" plain size="default" @click="openKnowledgeBaseSelector">
                  <el-icon class="mr-1"><Folder /></el-icon>
                  选择知识库
                </el-button>
                <el-button
                  v-if="currentKnowledgeBase"
                  type="danger"
                  plain
                  size="small"
                  @click="clearKnowledgeBase"
                  class="ml-2"
                >
                  <el-icon class="mr-1"><Close /></el-icon>清除
                </el-button>
              </div>
            </div>
            
            <!-- 输入提示 -->
            <div class="text-xs text-gray-500">
              <span class="mr-4">按 Shift + Enter 发送消息</span>
              <span v-if="mediaList.length > 0" class="text-blue-600">已选择 {{ mediaList.length }} 个附件</span>
            </div>
          </div>
          
          <div class="relative">
            <Flex align="end">
              <Sender
                submit-type="shiftEnter"
                placeholder="输入您的问题..."
                @submit="sendMessage"
                v-model:value="userInput"
                :loading="isInputDisabled"
                :disabled="isInputDisabled"
                :on-paste-file="pastFile"
              >
                <template #header>
                  <Sender.Header
                    title="上传附件"
                    :styles="{
                      content: {
                        padding: 0,
                      },
                    }"
                    :extra="mediaList.length ? `已选择 ${mediaList.length} 个文件` : undefined"
                    :open="open"
                    :on-open-change="openChange"
                    force-render
                  >
                    <Attachments
                      ref="attachmentsRef"
                      :customRequest="customRequest"
                      :items="items"
                      :on-change="fileChange"
                      :placeholder="placeholder"
                      :get-drop-container="getDropContainer"
                    />
                  </Sender.Header>
                </template>

                <template #prefix>
                  <Button
                    type="text"
                    v-if="currentModelType != 0"
                    @click="triggerOpen"
                    :badge="mediaList.length ? { count: mediaList.length } : undefined"
                  >
                    <template #icon>
                      <LinkOutlined />
                    </template>
                  </Button>
                </template>

                <template #suffix>
                  <Tooltip title="附件上传后将随消息一起发送">
                    <Button v-if="mediaList.length > 0" type="text" danger @click="clearMediaList">
                      <template #icon>
                        <DeleteOutlined />
                      </template>
                    </Button>
                  </Tooltip>
                </template>
              </Sender>
            </Flex>
          </div>
          <!-- 添加 AI 输出状态显示 -->
          <div v-if="isAiResponding" class="mt-2 flex items-center justify-between text-sm">
            <div class="flex items-center text-blue-600">
              <el-icon class="animate-spin mr-1">
                <Loading />
              </el-icon>
              <span>AI 正在思考中...</span>
            </div>
            <el-button type="danger" size="small" @click="stopAiResponse" class="!rounded-button">
              停止回答
            </el-button>
          </div>
        </div>
      </div>
    </div>
  </div>

  <!-- 重命名对话弹窗 -->
  <el-dialog v-model="renameDialogVisible" title="重命名对话" width="30%">
    <el-input v-model="newChatTitle" placeholder="请输入新的对话名称"></el-input>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="renameDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="confirmRename" class="!rounded-button">确认</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 模型选择弹窗 -->
  <el-dialog
    v-model="showModelSelector"
    title="选择 AI 模型"
    width="70%"
    :destroy-on-close="false"
    class="model-selector-dialog"
  >
    <div class="p-4">
      <!-- 顶部搜索和分类 -->
      <div class="flex flex-col mb-4">
        <el-input
          v-model="modelSearchKeyword"
          placeholder="搜索模型"
          prefix-icon="Search"
          clearable
          class="mb-4"
          @input="searchModels"
        />
        
        <!-- 分类切换 -->
        <div class="flex flex-wrap gap-2">
          <el-tag
            @click="selectModelCategory(null)"
            :effect="currentModelCategoryId === null ? 'dark' : 'plain'"
            class="cursor-pointer px-3 py-1.5"
            size="large"
          >
            <div class="flex items-center">
              <el-icon class="mr-1"><Menu /></el-icon>
              全部
            </div>
          </el-tag>
          
          <el-tag 
            v-for="category in modelCategoryList" 
            :key="category.id"
            @click="selectModelCategory(category.id)"
            :effect="currentModelCategoryId === category.id ? 'dark' : 'plain'"
            class="cursor-pointer px-3 py-1.5"
            size="large"
          >
            <div class="flex items-center">
              <img v-if="category.modelCategoryIcon" :src="category.modelCategoryIcon" class="w-4 h-4 mr-1 rounded" />
              <el-icon v-else class="mr-1"><Folder /></el-icon>
              {{ category.modelCategoryName }}
            </div>
          </el-tag>
        </div>
      </div>
      
      <!-- 模型列表 -->
      <div class="model-grid">
        <el-row :gutter="16">
          <el-col 
            :span="8" 
            v-for="model in filteredModelList" 
            :key="model.id"
            class="mb-4"
          >
            <el-card 
              shadow="hover" 
              :class="[
                'cursor-pointer transition-all duration-200 h-full relative',
                tempSelectedModelId === model.id ? 'border-blue-500 border-2' : '',
                model.id === currentModelId && model.id !== tempSelectedModelId ? 'border-green-500 border-2' : ''
              ]"
              @click="selectModel(model)"
            >
              <!-- 当前使用标记 -->
              <div v-if="model.id === currentModelId && model.id !== tempSelectedModelId" 
                class="absolute right-3 top-3 w-6 h-6 rounded-full bg-green-500 flex items-center justify-center shadow-md">
                <el-icon class="text-white"><Check /></el-icon>
              </div>
              
              <!-- 临时选中标记 -->
              <div v-if="model.id === tempSelectedModelId" 
                class="absolute right-3 top-3 w-6 h-6 rounded-full bg-blue-500 flex items-center justify-center shadow-md">
                <el-icon class="text-white"><Check /></el-icon>
              </div>
              
              <div class="flex flex-col h-full">
                <div class="flex items-start">
                  <!-- 模型图标 -->
                  <div class="flex-shrink-0 mr-3">
                    <div class="w-12 h-12 rounded-lg flex items-center justify-center overflow-hidden">
                      <img v-if="model.modelIcon" :src="model.modelIcon" class="w-full h-full object-cover" />
                      <el-icon v-else class="text-2xl text-blue-500"><ChatDotRound /></el-icon>
                    </div>
                  </div>
                  
                  <!-- 模型信息 -->
                  <div class="flex-1 min-w-0">
                    <h3 class="font-bold text-base text-gray-800 mb-1 truncate">{{ model.modelName }}</h3>
                    <p class="text-xs text-gray-500 line-clamp-2 mb-2 break-words">{{ model.modelDesc || '暂无描述' }}</p>
                  </div>
                </div>
                
                <div class="flex flex-wrap gap-2 mt-auto">
                  <el-tag size="small" type="info" effect="plain">{{ model.modelTypeName }}</el-tag>
                </div>
              </div>
            </el-card>
          </el-col>
        </el-row>
        
        <!-- 空状态 -->
        <div v-if="filteredModelList.length === 0" class="text-center py-10 text-gray-500">
          <el-icon class="text-5xl mb-3"><SearchFilled /></el-icon>
          <p>没有找到匹配的模型</p>
        </div>
      </div>
    </div>

    <template #footer>
      <div class="flex justify-between">
        <el-button @click="cancelModelSelection">取消</el-button>
        <el-button type="primary" @click="confirmModelSelection">确定</el-button>
      </div>
    </template>
  </el-dialog>

  <!-- 助手选择弹窗 -->
  <el-dialog
    v-model="showAssistantSelector"
    title="选择助手"
    width="70%"
    :destroy-on-close="false"
    class="assistant-dialog"
  >
    <div class="p-2">
      <el-input
        v-model="assistantKeyword"
        placeholder="搜索助手"
        class="mb-4"
        prefix-icon="Search"
        clearable
      />

      <el-row :gutter="16" class="assistant-grid">
        <el-col :span="6" v-for="assistant in assistantList" :key="assistant.id" class="mb-4">
          <el-card
            shadow="hover"
            :class="[
              'cursor-pointer h-full flex flex-col',
              tempSelectedAssistant?.id === assistant.id ? 'border-blue-500 border-2' : '',
              currentAssistant?.id === assistant.id ? 'border-green-500 border-2' : '',
            ]"
            @click="selectAssistant(assistant)"
          >
            <div class="flex items-center mb-3">
              <img
                :src="assistant.assistantIcon"
                class="w-12 h-12 rounded-full object-cover mr-3"
                onerror="this.src='https://ui-avatars.com/api/?name=AI&background=random'"
              />
              <div class="flex-1">
                <div class="font-bold text-gray-800">{{ assistant.assistantName }}</div>
                <div class="text-xs text-gray-500 flex items-center">
                  <el-icon class="mr-1"><ThumbUp /></el-icon>{{ assistant.likeCount }}
                </div>
              </div>
            </div>
            <div class="text-sm text-gray-600 line-clamp-2 flex-1">
              {{
                assistant.assistantPrompt.length > 100
                  ? assistant.assistantPrompt.substring(0, 100) + '...'
                  : assistant.assistantPrompt
              }}
            </div>
          </el-card>
        </el-col>
      </el-row>
    </div>

    <template #footer>
      <div class="flex justify-between">
        <el-button @click="clearAssistant">不使用助手</el-button>
        <el-button type="primary" @click="confirmAssistant">确定</el-button>
      </div>
    </template>
  </el-dialog>
  
  <!-- 知识库选择弹窗 -->
  <el-dialog
    v-model="showKnowledgeBaseSelector"
    title="选择知识库"
    width="70%"
    :destroy-on-close="false"
    class="knowledge-base-dialog"
  >
    <div class="p-4">
      <el-input
        v-model="knowledgeBaseKeyword"
        placeholder="搜索知识库"
        class="mb-4"
        prefix-icon="Search"
        clearable
        :loading="loadingKnowledgeBases"
      />

      <el-row :gutter="16" class="knowledge-base-grid">
        <el-col :span="8" v-for="kb in knowledgeBaseList" :key="kb.id" class="mb-4">
          <el-card
            shadow="hover"
            :class="[
              'cursor-pointer h-full flex flex-col',
              tempSelectedKnowledgeBase?.id === kb.id ? 'border-blue-500 border-2' : '',
              currentKnowledgeBase?.id === kb.id ? 'border-green-500 border-2' : '',
            ]"
            @click="selectKnowledgeBase(kb)"
          >
            <div class="flex items-center mb-3">
              <div class="w-12 h-12 rounded-lg flex items-center justify-center mr-3 bg-purple-100">
                <el-icon class="text-2xl text-purple-600"><Folder /></el-icon>
              </div>
              <div class="flex-1">
                <div class="font-bold text-gray-800">{{ kb.name }}</div>
                <div class="text-xs text-gray-500 flex items-center">
                  <span>{{ KnowledgeTypeDesc[kb.knowledgeType] || '文档' }}</span>
                  <span class="mx-1">•</span>
                  <span>{{ kb.documentCount || 0 }} 文档</span>
                </div>
              </div>
            </div>
            <div class="text-sm text-gray-600 line-clamp-2 flex-1">
              {{ kb.desc || '暂无描述' }}
            </div>
          </el-card>
        </el-col>
        
        <!-- 空状态显示 -->
        <el-empty v-if="knowledgeBaseList.length === 0" description="暂无知识库" />
      </el-row>
    </div>

    <template #footer>
      <div class="flex justify-between">
        <el-button @click="clearKnowledgeBase">不使用知识库</el-button>
        <el-button type="primary" @click="confirmKnowledgeBase">确定</el-button>
      </div>
    </template>
  </el-dialog>
</template>
<script lang="ts" setup>
import { ref, computed, onMounted, nextTick, watch, h } from 'vue'
import { Bubble } from 'ant-design-x-vue'
import { Typography } from 'ant-design-vue'
// @ts-ignore
import markdownit from 'markdown-it'
import { figure } from '@mdit/plugin-figure'
import { katex } from '@mdit/plugin-katex'
import { ElMessage, ElMessageBox, ElLoading } from 'element-plus'
import {
  getModelList,
  getAllModelList,
  getModelCategoryList,
  getCategoryModelList,
  getConversationList,
  getConversationMessages,
  sendChatMessage,
  createConversation,
  renameConversation,
  deleteConversation,
} from '@/api/ai'
import { get } from '../utils/request'
import { uploadToOss } from '../utils/upload'
import {
  User,
  ChatDotRound,
  Plus,
  ArrowDown,
  MoreFilled,
  Loading,
  UserFilled,
  Star as ThumbUp,
  Close,
  Check,
  List,
  Folder,
  Search,
  Search as SearchFilled,
  Menu,
} from '@element-plus/icons-vue'
import {
  CopyOutlined,
  CloudUploadOutlined,
  LinkOutlined,
  DeleteOutlined,
  FileOutlined,
  PictureOutlined,
  FileTextOutlined,
  DownloadOutlined,
  VideoCameraOutlined,
  SoundOutlined,
} from '@ant-design/icons-vue'
import { Button, Space, theme, Flex, Tooltip } from 'ant-design-vue'
import { Sender, Attachments } from 'ant-design-x-vue'
import { formatDate } from '@/utils/dateFormat'
import { createMathjaxInstance, mathjax } from '@mdit/plugin-mathjax'
import { plantuml } from '@mdit/plugin-plantuml'
import { AssistantItem } from '../types/assistant'
import { listKnowledge, KnowledgeTypeDesc } from '@/api/knowledge'

/** 文件上传 */
const mediaList = ref([])
const fileList = ref([])

const items = ref([])

// 获取文件类型
const getFileType = (filename) => {
  if (!filename) return 'application'
  const ext = filename.split('.').pop()?.toLowerCase()
  if (!ext) return 'application'

  if (['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg'].includes(ext)) {
    return 'image'
  } else if (['mp4', 'webm', 'ogg', 'mov'].includes(ext)) {
    return 'video'
  } else if (['mp3', 'wav', 'ogg', 'aac'].includes(ext)) {
    return 'audio'
  } else {
    return 'application'
  }
}

const attachmentsRef = ref(null)
const senderRef = ref(null)

const placeholder = (type) =>
  type === 'drop'
    ? {
        title: '拖放文件到此处',
      }
    : {
        icon: h(CloudUploadOutlined),
        title: '上传文件',
        description: '点击或拖动文件到此区域上传',
      }

const getDropContainer = () => senderRef.value?.nativeElement
const customRequest = (event) => {
  if (currentModelType.value == 0) {
    ElMessage.error('当前模型不支持文件上传')
    return
  }

  // 显示上传进度
  event.onProgress && event.onProgress({ percent: 0 })

  // 使用 OSS 上传
  uploadToOss(event.file, (percent) => {
    event.onProgress && event.onProgress({ percent })
  })
    .then((result) => {
      // 上传成功回调
      event.onSuccess && event.onSuccess({ url: result.url }, new XMLHttpRequest())

      // 处理返回的文件URL
      if (result.url) {
        // 添加到文件列表
        fileList.value.push(result.url)
        // 创建媒体对象
        const mediaItem = {
          id: Date.now().toString(),
          mimeType: getFileType(event.file.name || ''),
          data: result.url,
          name: event.file.name || `file-${Date.now()}`,
        }

        // 添加到文件列表
        mediaList.value.push(mediaItem)
      }
    })
    .catch((error) => {
      console.error('文件上传失败:', error)
      // 上传失败回调
      event.onError && event.onError(error)
    })
    .finally(() => {
      // 完成进度
      event.onProgress && event.onProgress({ percent: 100 })
    })
}
const pastFile = (firstFile, files) => {
  console.log('粘贴文件:', files?.length)
  if (currentModelType.value == 0) {
    ElMessage.error('当前模型不支持文件上传')
    return
  }
  if (files && files.length > 0) {
    // 直接使用已有的fileChange方法和customRequest方法处理文件
    open.value = true // 打开上传面板

    // 将FileList转换为数组
    const fileArray = Array.from(files)

    // 创建临时文件列表项
    const fileListItems = fileArray.map((file, index) => ({
      uid: `${Date.now()}_${index}`,
      name: file.name || `file_${index}`,
      originFileObj: file,
      status: 'uploading',
      percent: 0,
    }))

    // 更新文件列表显示
    items.value = [...items.value, ...fileListItems]

    // 手动触发每个文件的上传
    for (const fileItem of fileListItems) {
      customRequest({
        file: fileItem.originFileObj,
        onProgress: (e) => {
          // 更新进度
          const foundItem = items.value.find((item) => item.uid === fileItem.uid)
          if (foundItem) foundItem.percent = e.percent
        },
        onSuccess: () => {
          // 标记上传成功
          const foundItem = items.value.find((item) => item.uid === fileItem.uid)
          if (foundItem) foundItem.status = 'done'
        },
        onError: () => {
          // 标记上传失败
          const foundItem = items.value.find((item) => item.uid === fileItem.uid)
          if (foundItem) foundItem.status = 'error'
          ElMessage.error(`文件 ${fileItem.name} 上传失败`)
        },
      })
    }
  }
}
const fileChange = ({ fileList }) => (items.value = fileList)

const { token } = theme.useToken()
const open = ref(false)
const openChange = (v) => {
  open.value = v
}

const triggerOpen = () => {
  open.value = !open.value
}
const selectFileClick = () => {
  ElMessage.info('Mock select file')
}

defineOptions({ name: 'AXBubbleMarkdownSetup' })

const md = markdownit({
  html: true,
  breaks: true,
  linkify: true,
}).use(katex, plantuml)
const renderMarkdown = (content) =>
  h(Typography, null, {
    default: () => h('div', { innerHTML: md.render(content) }),
  })

// 模型列表
const modelList = ref([])
const modelCategoryList = ref([])
const currentModel = ref('')
const currentModelId = ref(null)
const currentModelType = ref(null)
const currentModelTypeName = ref('')
const currentModelCategoryId = ref(null)
const modelSearchKeyword = ref('')

// 初始化标志，避免在初始化期间触发保存
const isInitializing = ref(true)

// 分页参数
const pageParams = ref({
  page: 1,
  limit: 7,
  order: 'DESC',
  field: 'updateTime',
})

// 计算属性：根据当前分类和搜索关键词过滤模型列表
const filteredModelList = computed(() => {
  if (!modelList.value.length) return []
  
  let result = [...modelList.value]
  
  // 如果有搜索关键词
  if (modelSearchKeyword.value) {
    const keyword = modelSearchKeyword.value.toLowerCase()
    result = result.filter(model => 
      model.modelName.toLowerCase().includes(keyword) || 
      model.modelTypeName.toLowerCase().includes(keyword) ||
      (model.modelDesc && model.modelDesc.toLowerCase().includes(keyword))
    )
  }
  
  return result
})

// 会话列表
const chatHistory = ref([])
const totalCount = ref(0)
const currentChatIndex = ref(0)
const searchKeyword = ref('')

// 助手相关
const assistantList = ref([])
const currentAssistant = ref(null)
const tempSelectedAssistant = ref(null)
const showAssistantSelector = ref(false)
const assistantKeyword = ref('')

// 模型选择相关
const showModelSelector = ref(false)
const tempSelectedModelId = ref(null)
const tempSelectedModel = ref(null)

// 知识库相关
const knowledgeBaseList = ref([])
const currentKnowledgeBase = ref(null)
const tempSelectedKnowledgeBase = ref(null)
const showKnowledgeBaseSelector = ref(false)
const knowledgeBaseKeyword = ref('')
const loadingKnowledgeBases = ref(false)

// 获取模型列表
const fetchModelList = async () => {
  try {
    const [modelData, categoryData] = await Promise.all([
      getAllModelList(),
      getModelCategoryList()
    ])
    
    modelList.value = modelData
    modelCategoryList.value = categoryData
    
    // 移除自动设置默认模型的逻辑，让restoreUserPreferences来处理
    // if (modelData.length > 0) {
    //   currentModel.value = modelData[0].modelName
    //   currentModelId.value = modelData[0].id
    //   currentModelType.value = modelData[0].modelType
    //   currentModelTypeName.value = modelData[0].modelTypeName
    // }
  } catch (error) {
    console.error('获取模型列表失败:', error)
    ElMessage.error('获取模型列表失败')
  }
}

// 选择模型分类
const selectModelCategory = async (categoryId) => {
  currentModelCategoryId.value = categoryId
  
  try {
    if (categoryId === null) {
      // 获取所有模型
      const data = await getAllModelList()
      modelList.value = data
    } else {
      // 获取分类下的模型
      const data = await getCategoryModelList(categoryId)
      modelList.value = data
    }
  } catch (error) {
    console.error('获取分类模型列表失败:', error)
    ElMessage.error('获取分类模型列表失败')
  }
}

// 搜索模型
const searchModels = async () => {
  if (currentModelCategoryId.value === null) {
    // 搜索所有模型
    try {
      const data = await getAllModelList(modelSearchKeyword.value)
      modelList.value = data
    } catch (error) {
      console.error('搜索模型失败:', error)
    }
  } else {
    // 分类内搜索，前端过滤
    if (modelSearchKeyword.value) {
      const keyword = modelSearchKeyword.value.toLowerCase()
      // 不发请求，直接前端筛选
      try {
        const data = await getCategoryModelList(currentModelCategoryId.value)
        modelList.value = data.filter(model => 
          model.modelName.toLowerCase().includes(keyword) || 
          model.modelTypeName.toLowerCase().includes(keyword) ||
          (model.modelDesc && model.modelDesc.toLowerCase().includes(keyword))
        )
      } catch (error) {
        console.error('搜索分类模型失败:', error)
      }
    } else {
      // 关键词为空，恢复当前分类的所有模型
      try {
        const data = await getCategoryModelList(currentModelCategoryId.value)
        modelList.value = data
      } catch (error) {
        console.error('获取分类模型列表失败:', error)
      }
    }
  }
}

const chatHistoryRef = ref<HTMLElement | null>(null)
// 获取会话列表
const fetchConversationList = async () => {
  const loadingInstance = ElLoading.service({
    target: chatHistoryRef.value,
    text: '加载中',
  })
  try {
    const res = await getConversationList({
      keyword: searchKeyword.value,
      page: pageParams.value,
    })
    console.log('获取会话列表响应:', res)
    if (res.data) {
      chatHistory.value = res.data.map((chat) => ({
        ...chat,
        messages: [], // 初始化空消息数组
      }))
      totalCount.value = res.totalCount
      // 如果有会话数据，默认选中第一个
      if (chatHistory.value.length > 0 && currentChatIndex.value === 0) {
        currentChatIndex.value = 0
        // 自动加载第一个会话的消息
        await selectChat(0)
      }
    }
  } catch (error) {
    console.error('获取会话列表失败:', error)
    ElMessage.error('获取会话列表失败')
  } finally {
    loadingInstance.close()
  }
}

// 搜索会话
const handleSearch = () => {
  pageParams.value.page = 1
  fetchConversationList()
}

// 监听搜索关键词变化
watch(searchKeyword, () => {
  handleSearch()
})

// 当前选中的会话
const currentChat = computed(() => {
  const chat = chatHistory.value[currentChatIndex.value]
  console.log('当前选中的会话:', chat)

  if (!chat) {
    return {
      id: 0,
      type: 0,
      typeName: '',
      title: '',
      totalToken: 0,
      createTime: 0,
      updateTime: 0,
      messages: [],
    }
  }

  return {
    ...chat,
    messages: chat.messages || [],
  }
})

// 选择会话
const selectChat = async (index) => {
  isNewMessage.value = false
  const loadingInstance = ElLoading.service({
    target: chatContentRef.value,
    text: '加载中',
  })
  currentChatIndex.value = index
  const chat = chatHistory.value[index]
  if (chat) {
    const messages = await getConversationMessages(chat.id)
    chat.messages = messages.map((msg) => ({
      role: msg.type === 0 ? 'user' : 'assistant',
      content:
        typeof msg.messageContent === 'string'
          ? msg.messageContent
          : msg.messageContent && typeof msg.messageContent === 'object'
            ? msg.messageContent.content ||
              msg.messageContent.message ||
              msg.messageContent.code ||
              JSON.stringify(msg.messageContent, null, 2)
            : String(msg.messageContent),
      time: formatDate(msg.createTime),
      messageMediaList: msg.messageMediaList,
      createTime: msg.createTime,
    }))
    chatHistory.value = [...chatHistory.value]
    nextTick(scrollToBottom)
  }
  loadingInstance.close()
}

// 创建新会话
const createNewChat = async () => {
  try {
    const res = await createConversation({ title: '新对话', type: 0 })
    console.log('创建新会话响应:', res)
    
    // 创建新的会话对象
    const newChat = {
      ...res,
      messages: [],
    }
    
    // 如果会话列表为空，直接添加
    if (chatHistory.value.length === 0) {
      chatHistory.value.push(newChat)
    } else {
      // 否则插入到开头并移除最后一个（保持列表长度）
      chatHistory.value.unshift(newChat)
      if (chatHistory.value.length > pageParams.value.limit) {
    chatHistory.value.pop()
      }
    }
    
    currentChatIndex.value = 0
    userInput.value = ''
    // 总数加一
    totalCount.value++
    
    nextTick(() => {
      if (inputRef.value) inputRef.value.focus()
    })
  } catch (e) {
    console.error('创建会话失败:', e)
    ElMessage.error('创建会话接口异常')
    throw e // 重新抛出错误，以便调用方处理
  } finally {
    // 只在非自动创建的情况下刷新列表
    if (chatHistory.value.length > 0) {
    await fetchConversationList()
    }
  }
}

// 删除会话
const deleteChat = (index) => {
  ElMessageBox.confirm('确定要删除这个对话吗？此操作不可恢复。', '删除确认', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  })
    .then(async () => {
      try {
        const chatToDelete = chatHistory.value[index]
        await deleteConversation(chatToDelete.id)

        chatHistory.value.splice(index, 1)
        if (chatHistory.value.length === 0) {
          createNewChat()
        } else if (currentChatIndex.value >= chatHistory.value.length) {
          currentChatIndex.value = chatHistory.value.length - 1
        }

        ElMessage({
          type: 'success',
          message: '删除成功',
        })
      } catch (error) {
        console.error('删除会话失败:', error)
        ElMessage.error('删除会话失败')
      } finally {
        await fetchConversationList()
      }
    })
    .catch(() => {
      // 取消删除
    })
}

const userInput = ref('')
const isTyping = ref(false)
const chatContentRef = ref(null)
const inputRef = ref(null)
const renameDialogVisible = ref(false)
const newChatTitle = ref('')
const chatToRenameIndex = ref(-1)
const isAiResponding = ref(false)
const chatRequest = ref(null)
const isNewMessage = ref(false)
const sendMessage = async () => {
  console.log('sendMessage', userInput.value)
  if (!userInput.value.trim()) return
  if (isTyping.value) return
  if (isAiResponding.value) return

  // 检查是否需要创建新会话
  if (chatHistory.value.length === 0 || currentChat.value.id === 0) {
    console.log('检测到空会话列表，自动创建新会话')
    try {
      await createNewChat()
      // 等待会话创建完成后再继续发送消息
      await nextTick()
      // 确保新会话已经被选中
      if (chatHistory.value.length === 0 || currentChat.value.id === 0) {
        ElMessage.error('创建会话失败，请手动创建新会话')
        return
      }
    } catch (error) {
      console.error('自动创建会话失败:', error)
      ElMessage.error('创建会话失败，请手动创建新会话')
      return
    }
  }

  isNewMessage.value = true
  isTyping.value = true
  isAiResponding.value = true

  const now = Date.now()
  const messageContent = userInput.value

  let messageBuffer = ''
  let processedChunks = new Set()

  try {
    currentChat.value.messages.push({
      role: 'user',
      content: messageContent,
      time: formatDate(now),
      createTime: now,
      messageMediaList: [...mediaList.value],
    })

    const aiMessage = {
      role: 'assistant',
      content: '',
      time: formatDate(now + 1000), // AI回复时间设为当前时间+1秒
      createTime: now + 1000,
    }
    currentChat.value.messages.push(aiMessage)
    const aiMessageIndex = currentChat.value.messages.length - 1

    console.log('使用模型ID:', currentModelId.value, '模型名称:', currentModel.value)
    if (currentAssistant.value) {
      console.log(
        '同时使用助手:',
        currentAssistant.value.assistantName,
        '(ID:',
        currentAssistant.value.id,
        ')',
      )
    }
    if (currentKnowledgeBase.value) {
      console.log(
        '同时使用知识库:',
        currentKnowledgeBase.value.name,
        '(ID:',
        currentKnowledgeBase.value.id,
        ')',
      )
    }

    chatRequest.value = await sendChatMessage(
      {
        conversationId: currentChat.value.id,
        modelId: currentModelId.value || undefined,
        message: messageContent,
        modelName: currentModel.value,
        assistantId: currentAssistant.value?.id,
        knowledgeId: currentKnowledgeBase.value?.id,
        fileList: fileList.value,
      },
      (data) => {
        if (!isAiResponding.value) return // 如果已停止，不再处理新的响应

        isTyping.value = false
        const chunkId = data.id
        if (processedChunks.has(chunkId)) {
          return
        }
        processedChunks.add(chunkId)
        messageBuffer += data.content
        currentChat.value.messages[aiMessageIndex].content = messageBuffer
        nextTick(() => {
          scrollToBottom()
        })
      },
    )

    await chatRequest.value.promise

    userInput.value = ''

    if (currentChat.value.messages.length === 2) {
      currentChat.value.title =
        messageContent.length > 20 ? messageContent.substring(0, 20) + '...' : messageContent
    }

    // 发送完毕后确保滚动到底部
    isTyping.value = false
    await nextTick()
    scrollToBottom()
  } catch (error) {
    isTyping.value = false
    console.error('发送消息失败:', error)
    ElMessage.error('发送消息失败')
  } finally {
    items.value = []
    fileList.value = []
    mediaList.value = []
    isAiResponding.value = false
    chatRequest.value = null
  }
}

const scrollToBottom = () => {
  if (chatContentRef.value) {
    chatContentRef.value.scrollTop = chatContentRef.value.scrollHeight
  }
}

const handleEnterKey = (e) => {
  if (e.ctrlKey) {
    sendMessage()
  } else {
    // 允许正常的换行
    return true
  }
}

const clearInput = () => {
  userInput.value = ''
  if (inputRef.value) {
    inputRef.value.focus()
  }
}

const copyMessage = (text) => {
  navigator.clipboard.writeText(text).then(() => {
    ElMessage({
      message: '已复制到剪贴板',
      type: 'success',
      duration: 2000,
    })
  })
}

const changeModel = (modelName) => {
  // 找到对应的模型对象
  const selectedModel = modelList.value.find((m) => m.modelName === modelName)
  if (selectedModel) {
    currentModel.value = selectedModel.modelName
    currentModelId.value = selectedModel.id
    currentModelType.value = selectedModel.modelType
    currentModelTypeName.value = selectedModel.modelTypeName
    console.log(
      '选择模型:',
      selectedModel.modelName,
      '(ID:',
      selectedModel.id,
      ', 类型:',
      selectedModel.modelTypeName,
      ')',
    )
  }
  // 不再清除助手选择，允许模型和助手自由组合
  // 立即保存选择
  saveUserPreferences()
}

const renameChat = (index) => {
  chatToRenameIndex.value = index
  newChatTitle.value = chatHistory.value[index].title
  renameDialogVisible.value = true
}

const confirmRename = async () => {
  if (chatToRenameIndex.value >= 0 && newChatTitle.value.trim()) {
    const chat = chatHistory.value[chatToRenameIndex.value]
    try {
      const res = await renameConversation({ id: chat.id, title: newChatTitle.value.trim() })
      chat.title = newChatTitle.value.trim()
      ElMessage.success('重命名成功')
    } catch (e) {
      ElMessage.error('重命名接口异常')
    }
    renameDialogVisible.value = false
    chatToRenameIndex.value = -1
  }
}

// 在 script 部分添加分页处理函数
const handleSizeChange = (val) => {
  pageParams.value.page = 1
  pageParams.value.limit = Number(val)
  fetchConversationList()
}

const handleCurrentChange = (val) => {
  pageParams.value.page = val
  fetchConversationList()
}

// 监听当前会话消息数量变化，自动滚动到底部
watch(
  () => currentChat.value.messages.length,
  async () => {
    await nextTick()
    scrollToBottom()
  },
)

// 修改输入框的禁用状态
const isInputDisabled = computed(() => {
  return isTyping.value || isAiResponding.value
})

// 添加停止 AI 回答的方法
const stopAiResponse = () => {
  if (chatRequest.value) {
    chatRequest.value.cancel()
    chatRequest.value = null
  }
  isAiResponding.value = false
  isTyping.value = false
  // 如果当前消息是空的，则移除它
  if (currentChat.value.messages.length > 0) {
    const lastMessage = currentChat.value.messages[currentChat.value.messages.length - 1]
    if (lastMessage.role === 'assistant' && !lastMessage.content) {
      currentChat.value.messages.pop()
    }
  }
}

// 获取助手列表
const getAssistantList = (keyword) => {
  const params = keyword ? { keyword } : { keyword: '' }
  return get('/ai-api/ai/assistant/list', params)
}

// 获取助手列表
const fetchAssistantList = async () => {
  try {
    assistantList.value = await getAssistantList(assistantKeyword.value)
  } catch (error) {
    console.error('获取助手列表失败:', error)
    ElMessage.error('获取助手列表失败')
  }
}

// 监听助手关键词变化
watch(assistantKeyword, () => {
  fetchAssistantList()
})

// 清除当前助手
const clearAssistant = () => {
  currentAssistant.value = null
  tempSelectedAssistant.value = null
  showAssistantSelector.value = false

  console.log('清除助手，当前模型保持不变:', currentModel.value, '(ID:', currentModelId.value, ')')

  // 立即保存选择
  saveUserPreferences()
}

// 选择助手
const selectAssistant = (assistant) => {
  tempSelectedAssistant.value = assistant
}

// 确认选择助手
const confirmAssistant = () => {
  currentAssistant.value = tempSelectedAssistant.value
  showAssistantSelector.value = false
  // 立即保存选择
  saveUserPreferences()
}

// 获取知识库列表
const fetchKnowledgeBaseList = async (keyword = '') => {
  try {
    loadingKnowledgeBases.value = true
    const params = {
      keyword,
      page: {
        page: 1,
        limit: 100,
        order: 'DESC',
        field: 'createTime'
      }
    }
    
    const response = await listKnowledge(params)
    knowledgeBaseList.value = response.data || []
  } catch (error) {
    console.error('获取知识库列表失败:', error)
    ElMessage.error('获取知识库列表失败')
    knowledgeBaseList.value = []
  } finally {
    loadingKnowledgeBases.value = false
  }
}

// 选择知识库
const selectKnowledgeBase = (kb) => {
  tempSelectedKnowledgeBase.value = kb
}

// 确认选择知识库
const confirmKnowledgeBase = () => {
  currentKnowledgeBase.value = tempSelectedKnowledgeBase.value
  showKnowledgeBaseSelector.value = false
  // 保存用户选择
  saveUserPreferences()
}

// 清除当前知识库
const clearKnowledgeBase = () => {
  currentKnowledgeBase.value = null
  tempSelectedKnowledgeBase.value = null
  showKnowledgeBaseSelector.value = false
  // 保存用户选择
  saveUserPreferences()
}

// 打开知识库选择器
const openKnowledgeBaseSelector = () => {
  // 初始化临时选中的知识库为当前选中的知识库
  tempSelectedKnowledgeBase.value = currentKnowledgeBase.value
  fetchKnowledgeBaseList(knowledgeBaseKeyword.value)
  showKnowledgeBaseSelector.value = true
}

// 监听知识库关键词变化
watch(knowledgeBaseKeyword, () => {
  fetchKnowledgeBaseList(knowledgeBaseKeyword.value)
})

// 初始化
onMounted(async () => {
  try {
    // 先加载数据
    await Promise.all([
      fetchModelList(), 
      fetchConversationList(), 
      fetchAssistantList(),
      fetchKnowledgeBaseList()
    ])

    // 延迟一下确保数据已经加载完毕
    await nextTick()

    // 恢复之前选择的模型和助手
    await restoreUserPreferences()
    
    // 初始化完成，允许保存操作
    isInitializing.value = false
    
    console.log('初始化完成，当前模型:', currentModel.value, '当前助手:', currentAssistant.value?.assistantName, '当前知识库:', currentKnowledgeBase.value?.name)

    // 再次nextTick确保UI更新
    nextTick(() => {
      scrollToBottom()
      if (inputRef.value) {
        inputRef.value.focus()
      }
    })
  } catch (error) {
    console.error('初始化加载失败:', error)
    ElMessage.error('初始化加载失败')
    // 即使出错也要结束初始化状态
    isInitializing.value = false
  }
})

// 保存用户偏好设置到本地存储
const saveUserPreferences = () => {
  // 如果正在初始化，不执行保存操作
  if (isInitializing.value) {
    console.log('正在初始化，跳过保存操作')
    return
  }
  
  console.log('保存用户偏好:', currentModel.value, currentAssistant.value?.assistantName, currentKnowledgeBase.value?.name)

  // 保存当前模型
  if (currentModel.value) {
    localStorage.setItem('eon-mind-current-model', currentModel.value)
    localStorage.setItem('eon-mind-current-model-id', currentModelId.value?.toString() || '')
    localStorage.setItem('eon-mind-current-model-type-name', currentModelTypeName.value || '')
  }

  // 保存当前助手
  if (currentAssistant.value) {
    localStorage.setItem(
      'eon-mind-current-assistant',
      JSON.stringify({
        id: currentAssistant.value.id,
        assistantName: currentAssistant.value.assistantName,
        assistantIcon: currentAssistant.value.assistantIcon,
        assistantPrompt: currentAssistant.value.assistantPrompt,
        likeCount: currentAssistant.value.likeCount,
        createTime: currentAssistant.value.createTime,
        updateTime: currentAssistant.value.updateTime,
      }),
    )
  } else {
    localStorage.removeItem('eon-mind-current-assistant')
  }
  
  // 保存当前知识库
  if (currentKnowledgeBase.value) {
    localStorage.setItem(
      'eon-mind-current-knowledge-base',
      JSON.stringify({
        id: currentKnowledgeBase.value.id,
        name: currentKnowledgeBase.value.name,
        knowledgeType: currentKnowledgeBase.value.knowledgeType,
        desc: currentKnowledgeBase.value.desc
      })
    )
  } else {
    localStorage.removeItem('eon-mind-current-knowledge-base')
  }
}

// 从本地存储中恢复用户偏好设置
const restoreUserPreferences = async () => {
  console.log('开始恢复用户设置...')
  console.log(
    '当前模型列表:',
    modelList.value.map((m) => `${m.modelName}(ID:${m.id})`),
  )
  console.log('当前助手列表长度:', assistantList.value.length)

  // 恢复选择的模型(优先使用ID恢复)
  const savedModelId = localStorage.getItem('eon-mind-current-model-id')
  const savedModelName = localStorage.getItem('eon-mind-current-model')

  console.log('保存的模型ID:', savedModelId, '保存的模型名称:', savedModelName)

  let modelRestored = false

  // 先尝试通过ID找模型
  if (savedModelId && savedModelId !== 'null') {
    const modelId = parseInt(savedModelId)
    const foundModel = modelList.value.find((m) => m.id === modelId)
    if (foundModel) {
      currentModel.value = foundModel.modelName
      currentModelId.value = foundModel.id
      currentModelType.value = foundModel.modelType
      currentModelTypeName.value = foundModel.modelTypeName
      console.log(
        '通过ID恢复模型:',
        foundModel.modelName,
        '(ID:',
        foundModel.id,
        ', 类型:',
        foundModel.modelTypeName,
        ')',
      )
      modelRestored = true
    }
  }

  // 如果ID没找到，尝试通过名称找
  if (
    !modelRestored &&
    savedModelName &&
    modelList.value.some((model) => model.modelName === savedModelName)
  ) {
    const foundModel = modelList.value.find((m) => m.modelName === savedModelName)
    if (foundModel) {
      currentModel.value = foundModel.modelName
      currentModelId.value = foundModel.id
      currentModelType.value = foundModel.modelType
      currentModelTypeName.value = foundModel.modelTypeName
      console.log(
        '通过名称恢复模型:',
        foundModel.modelName,
        '(ID:',
        foundModel.id,
        ', 类型:',
        foundModel.modelTypeName,
        ')',
      )
      modelRestored = true
    }
  }

  // 如果都没找到，使用第一个模型
  if (!modelRestored && modelList.value.length > 0) {
    currentModel.value = modelList.value[0].modelName
    currentModelId.value = modelList.value[0].id
    currentModelType.value = modelList.value[0].modelType
    currentModelTypeName.value = modelList.value[0].modelTypeName
    console.log(
      '使用默认模型:',
      currentModel.value,
      '(ID:',
      currentModelId.value,
      ', 类型:',
      modelList.value[0].modelTypeName,
      ')',
    )
  }

  // 恢复选择的助手
  try {
    const savedAssistantJson = localStorage.getItem('eon-mind-current-assistant')
    if (savedAssistantJson) {
      const savedAssistant = JSON.parse(savedAssistantJson)
      console.log('保存的助手:', savedAssistant)

      // 检查助手是否在当前列表中
      const foundAssistant = assistantList.value.find((a) => a.id === savedAssistant.id)
      if (foundAssistant) {
        currentAssistant.value = foundAssistant
        console.log('已恢复选择的助手:', foundAssistant.assistantName)
      } else {
        console.log('保存的助手不在当前列表中')
      }
    } else {
      console.log('没有保存的助手')
    }
  } catch (e) {
    console.error('恢复助手设置失败:', e)
    localStorage.removeItem('eon-mind-current-assistant')
  }
  
  // 恢复选择的知识库
  try {
    const savedKnowledgeBaseJson = localStorage.getItem('eon-mind-current-knowledge-base')
    if (savedKnowledgeBaseJson) {
      const savedKnowledgeBase = JSON.parse(savedKnowledgeBaseJson)
      console.log('保存的知识库:', savedKnowledgeBase)
      
      // 获取知识库列表
      await fetchKnowledgeBaseList()
      
      // 检查知识库是否在当前列表中
      const foundKnowledgeBase = knowledgeBaseList.value.find((kb) => kb.id === savedKnowledgeBase.id)
      if (foundKnowledgeBase) {
        currentKnowledgeBase.value = foundKnowledgeBase
        console.log('已恢复选择的知识库:', foundKnowledgeBase.name)
      } else {
        console.log('保存的知识库不在当前列表中')
      }
    } else {
      console.log('没有保存的知识库')
    }
  } catch (e) {
    console.error('恢复知识库设置失败:', e)
    localStorage.removeItem('eon-mind-current-knowledge-base')
  }
}

// 监听模型变化，保存到本地存储
watch(currentModel, () => {
  saveUserPreferences()
})

// 监听模型分类变化，保存到本地存储
watch(currentModelCategoryId, () => {
  saveUserPreferences()
})

// 监听助手变化，保存到本地存储
watch(currentAssistant, () => {
  saveUserPreferences()
})

// 监听知识库变化，保存到本地存储
watch(currentKnowledgeBase, () => {
  saveUserPreferences()
})

const clearMediaList = () => {
  mediaList.value = []
  items.value = []
  ElMessage.success('已清除所有附件')
}

// 预览图片
const previewImage = (imageUrl) => {
  // 创建一个新窗口显示图片
  const newWindow = window.open('', '_blank')
  if (newWindow) {
    newWindow.document.write(`
      <html>
        <head>
          <title>图片预览</title>
          <style>
            body { 
              margin: 0; 
              padding: 20px; 
              background: #000; 
              display: flex; 
              justify-content: center; 
              align-items: center; 
              min-height: 100vh; 
            }
            img { 
              max-width: 100%; 
              max-height: 100%; 
              object-fit: contain; 
            }
          </style>
        </head>
        <body>
          <img src="${imageUrl}" alt="预览图片" />
        </body>
      </html>
    `)
  }
}

// 下载文件
const downloadFile = (media) => {
  try {
    const link = document.createElement('a')
    link.href = media.data
    link.download = media.name || 'download'
    link.target = '_blank'
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    ElMessage.success('文件下载已开始')
  } catch (error) {
    console.error('文件下载失败:', error)
    ElMessage.error('文件下载失败')
  }
}

// 从 URL 获取文件扩展名
const getFileExtensionFromUrl = (url) => {
  if (!url) return ''
  const urlParts = url.split('?')[0] // 移除查询参数
  const pathParts = urlParts.split('/')
  const fileName = pathParts[pathParts.length - 1]
  const extensionMatch = fileName.match(/\.([^.]+)$/)
  return extensionMatch ? extensionMatch[1].toLowerCase() : ''
}

// 判断是否为图片文件
const isImageFile = (url) => {
  const ext = getFileExtensionFromUrl(url)
  return ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'bmp', 'ico'].includes(ext)
}

// 判断是否为视频文件
const isVideoFile = (url) => {
  const ext = getFileExtensionFromUrl(url)
  return ['mp4', 'webm', 'ogg', 'mov', 'avi', 'wmv', 'flv', 'mkv'].includes(ext)
}

// 判断是否为音频文件
const isAudioFile = (url) => {
  const ext = getFileExtensionFromUrl(url)
  return ['mp3', 'wav', 'ogg', 'aac', 'flac', 'm4a', 'wma'].includes(ext)
}

// 获取文件类型文本（基于 URL 后缀）
const getFileTypeText = (url) => {
  const ext = getFileExtensionFromUrl(url)
  
  if (isImageFile(url)) {
    return '图片文件'
  } else if (isVideoFile(url)) {
    return '视频文件'
  } else if (isAudioFile(url)) {
    return '音频文件'
  } else if (['pdf'].includes(ext)) {
    return 'PDF文档'
  } else if (['doc', 'docx'].includes(ext)) {
    return 'Word文档'
  } else if (['xls', 'xlsx'].includes(ext)) {
    return 'Excel表格'
  } else if (['ppt', 'pptx'].includes(ext)) {
    return 'PPT演示文稿'
  } else if (['txt', 'md', 'json', 'xml', 'csv'].includes(ext)) {
    return '文本文件'
  } else if (['zip', 'rar', '7z', 'tar', 'gz'].includes(ext)) {
    return '压缩文件'
  } else {
    return ext ? `${ext.toUpperCase()}文件` : '文件'
  }
}

// 选择模型（点击卡片时调用）
const selectModel = (model) => {
  tempSelectedModelId.value = model.id
  tempSelectedModel.value = model
}

// 确认选择模型（点击确定按钮时调用）
const confirmModelSelection = () => {
  if (tempSelectedModel.value) {
    changeModel(tempSelectedModel.value.modelName)
  }
  showModelSelector.value = false
}

// 取消选择模型
const cancelModelSelection = () => {
  tempSelectedModelId.value = null
  tempSelectedModel.value = null
  showModelSelector.value = false
}

// 打开模型选择器
const openModelSelector = () => {
  // 初始化临时选中的模型为当前选中的模型
  const currentSelectedModel = modelList.value.find(m => m.id === currentModelId.value)
  if (currentSelectedModel) {
    tempSelectedModelId.value = currentSelectedModel.id
    tempSelectedModel.value = currentSelectedModel
  } else {
    tempSelectedModelId.value = null
    tempSelectedModel.value = null
  }
  showModelSelector.value = true
}

// 处理下拉菜单命令
const handleCommand = (command, index) => {
  if (command === 'rename') {
    renameChat(index);
  } else if (command === 'delete') {
    deleteChat(index);
  }
}

// 计算总页数
const totalPages = computed(() => {
  return Math.ceil(totalCount.value / pageParams.value.limit) || 1;
});

// 计算要显示的页码
const displayedPages = computed(() => {
  const current = pageParams.value.page;
  const total = totalPages.value;
  
  if (total <= 5) {
    return Array.from({ length: total }, (_, i) => i + 1);
  }
  
  if (current <= 3) {
    return [1, 2, 3, 4, 5];
  }
  
  if (current >= total - 2) {
    return [total - 4, total - 3, total - 2, total - 1, total];
  }
  
  return [current - 2, current - 1, current, current + 1, current + 2];
});

// 处理上一页
const handlePrevPage = () => {
  if (pageParams.value.page > 1) {
    pageParams.value.page--;
    fetchConversationList();
  }
};

// 处理下一页
const handleNextPage = () => {
  if (pageParams.value.page < totalPages.value) {
    pageParams.value.page++;
    fetchConversationList();
  }
};
</script>
<style scoped>
.pagination-bar {
  margin: 0 auto;
}

.pagination-select {
  min-width: 70px;
}

/* 样式优化 */
.markdown-content pre {
  position: relative;
  background-color: #f5f5f5;
  border-radius: 4px;
  padding: 16px;
  margin: 16px 0;
}

.markdown-content pre code {
  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
  font-size: 14px;
}

.copy-btn {
  position: absolute;
  top: 8px;
  right: 8px;
  padding: 4px 8px;
  font-size: 12px;
  color: #666;
  background-color: #fff;
  border: 1px solid #ddd;
  border-radius: 3px;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.2s;
}

.markdown-content pre:hover .copy-btn {
  opacity: 1;
}

.copy-btn:hover {
  background-color: #f0f0f0;
}

/* 其他样式优化 */
.markdown-content h1,
.markdown-content h2 {
  border-bottom: 1px solid #eaecef;
  padding-bottom: 0.3em;
}

.markdown-content blockquote {
  border-left: 4px solid #dfe2e5;
  padding: 0 1em;
  color: #6a737d;
}

.markdown-content table {
  border-collapse: collapse;
  width: 100%;
  margin: 16px 0;
}

.markdown-content table th,
.markdown-content table td {
  border: 1px solid #dfe2e5;
  padding: 6px 13px;
}

.markdown-content table th {
  background-color: #f6f8fa;
}

.assistant-grid {
  max-height: 60vh;
  overflow-y: auto;
  padding: 0 10px;
}
.line-clamp-2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.assistant-dialog .el-card {
  transition: all 0.3s ease;
}

.assistant-dialog .el-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}

.assistant-dialog .el-card.border-blue-500 {
  position: relative;
  background-color: rgba(59, 130, 246, 0.05);
}

.assistant-dialog .el-card.border-blue-500::after {
  content: '✓';
  position: absolute;
  top: -8px;
  right: -8px;
  width: 24px;
  height: 24px;
  background-color: #3b82f6;
  color: white;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: bold;
}

/* 模型选择弹窗样式 */
.model-selector-dialog .model-grid {
  max-height: 60vh;
  overflow-y: auto;
  padding: 0 10px;
}

.model-selector-dialog .el-card {
  transition: all 0.3s ease;
  border-radius: 8px;
  overflow: hidden;
  min-height: 150px;
}

.model-selector-dialog .el-card .el-card__body {
  height: 100%;
  padding: 12px;
}

.model-selector-dialog .el-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}

/* 修改选中模型的样式 */
.model-selector-dialog .el-card.border-blue-500 {
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.7);
  position: relative;
}

/* 当前使用模型的样式 */
.model-selector-dialog .el-card.border-green-500 {
  box-shadow: 0 0 0 2px rgba(34, 197, 94, 0.7);
  position: relative;
}

/* 标签样式 */
.model-selector-dialog .el-tag {
  transition: all 0.2s ease;
}

.model-selector-dialog .el-tag.el-tag--plain:hover {
  background-color: #f0f9ff;
  border-color: #3b82f6;
  color: #3b82f6;
}

.model-selector-dialog .el-tag.el-tag--dark {
  background-color: #3b82f6;
  border-color: #3b82f6;
}

/* 知识库选择弹窗样式 */
.knowledge-base-dialog .knowledge-base-grid {
  max-height: 60vh;
  overflow-y: auto;
  padding: 0 10px;
}

.knowledge-base-dialog .el-card {
  transition: all 0.3s ease;
  min-height: 150px;
}

.knowledge-base-dialog .el-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}

.knowledge-base-dialog .el-card.border-blue-500 {
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.7);
}

.knowledge-base-dialog .el-card.border-green-500 {
  box-shadow: 0 0 0 2px rgba(34, 197, 94, 0.7);
}
</style>
